from flask import current_app
from flask_login import UserMixin
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from itsdangerous.exc import BadSignature, SignatureExpired

from blog import login_manager, db


# 关于user_loader详解
# https://blog.csdn.net/gymaisyl/article/details/86649253
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


# 命令行方式创建数据库
# from app import db
# db.create_all()  # db.drop_all() 删除所有表结构和数据
class User(db.Model, UserMixin):
    """用户模型， 字段
    id: 唯一标识
    username: 用户名
    email: 邮箱
    avatar: 个人头像
    password: 加密后的密码
    """
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(32), unique=True, nullable=False)
    email = db.Column(db.String(128), unique=True, nullable=False)
    avatar = db.Column(db.String(24), nullable=False, default='default.jpg')
    password = db.Column(db.String(128), nullable=False)
    # 不是真实存在的数据列，用户和帖子是一对多关系，backref参数方便反向查找
    # post = Post.query.first()
    # post.user返回User对象
    # https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/#one-to-many-relationships
    posts = db.relationship('Post', backref='user', lazy=True)

    def __repr__(self):
        return f'User({self.username}, {self.email}, {self.avatar})'

    def get_reset_token(self, expires=900):  # 15min
        """生成重置密碼令牌"""
        s = Serializer(current_app.config['SECRET_KEY'], expires)
        return s.dumps({'user_id': self.id}).decode()

    @staticmethod
    def check_reset_token(token):
        """判斷令牌是否有效，如果有效則返回該令牌對應的用戶，否則返回
        空"""
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            user_id = s.loads(token)['user_id']
        except (BadSignature, SignatureExpired):
            return None
        else:
            return User.query.get(user_id)


